﻿using System;
using Lypshare.Flow.Packets;
using Lypshare.Net.Client;
using Lypshare.Net;

namespace Lypshare.Flow
{
	/// <summary>
	/// Flow control.
	/// </summary>
	/// <exception cref='ArgumentNullException'>
	/// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> .
	/// </exception>
    public abstract class FlowControl : IFlowControl
    {
        // --------------------------------------------------------
        // Class Variables
        // --------------------------------------------------------


        /// <summary>
        /// The _end point.
        /// </summary>
        private FlowEndPoint _endPoint = null;


        // --------------------------------------------------------
        // Class Properties
        // --------------------------------------------------------


        /// <summary>
        /// Gets the end point.
        /// </summary>
        /// <value>
        /// The end point.
        /// </value>
        public FlowEndPoint EndPoint
        {
            get { return _endPoint; }

        } // Property: EndPoint


        /// <summary>
        /// Gets a value indicating whether this instance is empty.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is empty; otherwise, <c>false</c>.
        /// </value>
        public abstract bool IsEmpty 
        { 
            get; 

        } // Property: IsEmpty


        // --------------------------------------------------------
        // Class Functions
        // --------------------------------------------------------


        /// <summary>
        /// Initializes a new instance of the <see cref="Lypshare.Flow.FlowControl"/> class.
        /// </summary>
        /// <param name='endPoint'>
        /// End point.
        /// </param>
        /// <exception cref='ArgumentNullException'>
        /// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> .
        /// </exception>
        public FlowControl(FlowEndPoint endPoint)
        {
            if (endPoint == null)
                throw new ArgumentNullException("endPoint");

            _endPoint = endPoint;

        } // Constructor


        /// <summary>
        /// Send the specified packet.
        /// </summary>
        /// <param name='packet'>
        /// Packet.
        /// </param>
        public abstract void Send(Packet packet);


        /// <summary>
        /// Accept the specified packet.
        /// </summary>
        /// <param name='packet'>
        /// If set to <c>true</c> packet.
        /// </param>
        public abstract bool Accept(FlowPacket packet);


        /// <summary>
        /// Acknowledge the specified packet.
        /// </summary>
        /// <param name='packet'>
        /// Packet.
        /// </param>
        public abstract Packet[] Acknowledge(AckPacket packet);


        /// <summary>
        /// Performs application-defined tasks associated with freeing or resetting resources.
        /// </summary>
        /// <remarks>
        /// Call <see cref="Dispose"/> when you are finished using the <see cref="Lypshare.Flow.FlowControl"/>.
        /// The <see cref="Dispose"/> method leaves the <see cref="Lypshare.Flow.FlowControl"/> in an unusable
        /// state. After calling <see cref="Dispose"/>, you must release all references to the
        /// <see cref="Lypshare.Flow.FlowControl"/> so the garbage collector can reclaim the memory that the
        /// <see cref="Lypshare.Flow.FlowControl"/> was occupying.
        /// </remarks>
        public abstract void Dispose();

    } // class FlowControl
} // namespace Lypshare.Flow